#ifndef RTPS_SPDP_H
#define RTPS_SPDP_H

#include "lwip/sys.h"
#include "rtps/common/types.h"
#include "rtps/config.h"
#include "ucdr/microcdr.h"

#include "rtps/entities/Participant.h"
#include "rtps/entities/Reader.h"
#include "rtps/entities/Writer.h"
#include "rtps/discovery/BuiltInEndpoints.h"
#include "rtps/discovery/ParticipantProxyData.h"
#include <pthread.h>
#include <stdint-gcc.h>
#include <stdbool.h>

#if SPDP_VERBOSE && RTPS_GLOBAL_VERBOSE
#include "rtps/utils/printutils.h"
#define SPDP_LOG(...)                                                          \
  if (true) {                                                                  \
    printf("[SPDP] ");                                                         \
    printf(__VA_ARGS__);                                                       \
    printf("\n");                                                              \
  }
#else
#define SPDP_LOG(...) //
#endif

// typedef struct sys_mutex* sys_mutex_t;

// struct sys_mutex {
//   pthread_mutex_t mutex;
// };

struct rtps_Participant;
struct rtps_Writer;
struct rtps_Reader;
struct rtps_ReaderCacheChange;

struct rtps_SPDPAgent {
	struct rtps_Participant *mp_participant;
	struct rtps_BuiltInEndpoints m_buildInEndpoints;
	bool m_running;
	uint8_t m_outputBuffer[400];
	uint8_t m_inputBuffer[400];
	struct rtps_ParticipantProxyData m_proxyDataBuffer;   // ?
	struct ucdrBuffer m_microbuffer;   // ?
	uint8_t m_cycleHB;

	sys_mutex_t m_mutex;   // mutex ?
	bool initialized;
};

/* private */
void rtps_SPDPAgent_receiveCallback(void *callee, const ReaderCacheChange *cacheChange);
void rtps_SPDPAgent_handleSPDPPackage(struct rtps_SPDPAgent *this, const ReaderCacheChange *cacheChange);
void rtps_SPDPAgent_configureEndianessAndOptions(ucdrBuffer *buffer);
void rtps_SPDPAgent_processProxyData(struct rtps_SPDPAgent *this);
bool rtps_SPDPAgent_addProxiesForBuiltInEndpoints(struct rtps_SPDPAgent *this);

void rtps_SPDPAgent_addInlineQos(struct rtps_SPDPAgent *this);
void rtps_SPDPAgent_addParticipantParameters(struct rtps_SPDPAgent *this);
void rtps_SPDPAgent_endCurrentList(struct rtps_SPDPAgent *thi);

void rtps_SPDPAgent_runBroadcast(void *args);

/* public */
void rtps_SPDPAgent_distruct(struct rtps_SPDPAgent *this);
void rtps_SPDPAgent_init(struct rtps_SPDPAgent *this, struct rtps_Participant *participant, struct rtps_BuiltInEndpoints *endpoints);
void rtps_SPDPAgent_start(struct rtps_SPDPAgent *this);
void rtps_SPDPAgent_stop(struct rtps_SPDPAgent *this);

#endif /* RTPS_SPDP_H */
